package com.duoec.dw.lineage.core.utils;

import com.duoec.dw.lineage.dto.SqlScriptChangeLog;
import com.duoec.dw.lineage.dto.SqlScriptDto;
import com.google.common.base.Splitter;
import com.google.common.collect.Lists;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

/**
 * @author xuwenzhen
 */
public class ScriptInfoUtils {
    private static final Logger logger = LoggerFactory.getLogger(ScriptInfoUtils.class);
    public static final String STR_PURPOSE = "-- purpose";
    public static final String COMMENT_PREFIX = "--";
    public static final String COLON_STR = ":";
    public static final String COMMENT_PREFIX3 = "-- ==";
    public static final String STR_BLACK_SPACE_3 = "  ";
    public static final String COMMENT_TURN_LINE = "--                         ";
    public static final String TURN_LINE = "\n";
    private static final int MIN_LINE_LEN = 10;

    private ScriptInfoUtils() {
    }

    /**
     * 解析脚本，获取脚本内的一些注释信息
     *
     * @param script 脚本内容
     * @return 脚本内抽取的注释信息
     */
    public static SqlScriptDto analyse(String script) {
        Iterator<String> it = Splitter.on(TURN_LINE)
                .trimResults()
                .omitEmptyStrings()
                .split(script)
                .iterator();
        List<String> lines = Lists.newArrayList(it);

        SqlScriptDto sqlScriptDto = new SqlScriptDto();
        List<SqlScriptChangeLog> changeLogs = Lists.newArrayList();
        sqlScriptDto.setChangeLogs(changeLogs);
        boolean start = false;
        boolean logStart = false;
        for (String line : lines) {
            String lowerLine = line.toLowerCase();
            if (!start && line.startsWith(COMMENT_PREFIX)) {
                start = true;
            } else if (lowerLine.startsWith(STR_PURPOSE)) {
                //解析 purpose
                int index = line.indexOf(COLON_STR);
                if (index > -1) {
                    String purpose = line.substring(index + 1).trim();
                    sqlScriptDto.setPurpose(purpose);
                }
            } else if (start && !line.startsWith(COMMENT_PREFIX)) {
                //结束
                break;
            } else if (start && !logStart && lowerLine.startsWith("-- date generated")) {
                logStart = true;
            } else if (logStart) {
                //解析变更日志
                if (line.startsWith(COMMENT_PREFIX3)) {
                    //结束
                    break;
                }
                SqlScriptChangeLog log = analyseChangeLog(line, changeLogs);
                if (log == null) {
                    continue;
                }
                changeLogs.add(log);
            }
        }
        if (StringUtils.isEmpty(sqlScriptDto.getPurpose())) {
            logger.warn("不完整脚本注释，请编写：{}", STR_PURPOSE);
        }
        if (CollectionUtils.isEmpty(sqlScriptDto.getChangeLogs())) {
            logger.warn("不完整脚本注释，请编写变更信息！");
        }

        return sqlScriptDto;
    }

    private static SqlScriptChangeLog analyseChangeLog(String line, List<SqlScriptChangeLog> changeLogs) {
        if (line.length() < MIN_LINE_LEN) {
            return null;
        }
        line = line.replaceAll("\\t", "    ");
        if (line.startsWith(COMMENT_TURN_LINE)) {
            if (changeLogs.isEmpty()) {
                return null;
            }
            SqlScriptChangeLog log = changeLogs.get(changeLogs.size() - 1);
            String desc = line.substring(COMMENT_TURN_LINE.length()).trim();
            log.setDesc(log.getDesc() + TURN_LINE + desc);
            return null;
        }
        SqlScriptChangeLog log = new SqlScriptChangeLog();
        line = line.substring(3);
        int index = line.indexOf(STR_BLACK_SPACE_3);
        if (index == -1) {
            return null;
        }
        DateFormat fmt = new SimpleDateFormat("yyyy-MM-dd");
        String dateStr = line.substring(0, index).trim();
        try {
            Date date = fmt.parse(dateStr);
            log.setTime(date.getTime());
        } catch (ParseException e) {
            logger.warn("日期格式错误：{}", dateStr, e);
            return null;
        }
        line = line.substring(index + STR_BLACK_SPACE_3.length()).trim();
        index = line.indexOf(STR_BLACK_SPACE_3);
        if (index == -1) {
            return null;
        }
        String userName = line.substring(0, index);
        String desc = line.substring(index).trim();
        log.setUserName(userName);
        log.setDesc(desc);
        return log;
    }
}
